/**
 * The main syslib class
 * @class syslib
 * @version 0.5.3
 * @author Gabriel Ricci - gabrielricci@gmail.com
 * @static
 */ 
var syslib = {
	version : "0.5.3",
	
	path : "",
	lookAndFeel : "default/",
	componentsPath : this.path + "themes/",
	srcPath : this.path + "src",
	debug : false,
	
	options : {
		path : "", 
		lookAndFeel : "", 
		debug : false, 
		enableUI : false, 
		enableFX : false, 
		effects : [] 
	}, 

	init : function(options){
		if(options.constructor == Object){
			// extend the options
			syslib.object.extend(this.options, options);
			
			// path
			if(__valid(this.options.path)){
				if(this.options.path.charAt(options.path.length + 1) != "/"){
					this.path = this.options.path + "/";
				} else {
					this.path = this.options.path;
				}
				this.srcPath 			= this.path + "src/";
				this.componentsPath 	= this.path + "components/";
			}
			var path = this.path;

			// look and feel
			if(__valid(options.lookAndFeel)){
				var path = this.path;
				if(options.lookAndFeel.charAt(options.lookAndFeel.length) != "/"){
					this.lookAndFeel = options.lookAndFeel + "/";
				} else {
					this.lookAndFeel = options.lookAndFeel;
				}
			}

			// debug
			if(this.options.debug){
				// set the debug flag 
				syslib.debug = true;
				
				// debug console
				syslib.console.createConsole();
				
				// events
				window.onerror = function ( err, url, line ) {
					syslib.messages.error("Javascript error(" + (url) + ") on line "+line+", see: "+err);
				};
			}

			// user interface
			if(__valid(this.options.enableUI) && this.options.enableUI === true){
		
				// schedule the event
				syslib.event.listen("load", window, function(){
					// import the user interface component
					syslib.io.importScript(path + "syslib_ui.js", {
						onComplete : function(){
							// verbose
							syslib.messages.info("syslib.init(): User interface components loaded");
							
							// try to start the ui system
							var attempts = 1;
							var started = false;
							while(!started && attempts <= 200){
								try{
									// start the ui
									syslib.ui.init();
									
									// set as started and cancel the loop
									started = true;
								} catch(e){
									// increase the number of attempts
									attempts++;
								
									// set as not started and go to the next loop
									started = false;
									continue;
								}
							}
						}
					});
				});
			}
			
			// history
			if (!__valid(options.history || options.history === true)) {
				setTimeout(function(){
					// load te history engine
					syslib.history.init();
				}, 2000);
			}
		}

		// output
		syslib.messages.info('SystemLibrary Javascript Framework Version ' + this.version + " is now ready!");
	},

	/**
	 * Load the stylesheet for the component
	 * @param {Object} component The specified component
	 */
	loadStyleForComponent : function(component){
		syslib.io.importStyle(syslib.path + "themes/" + syslib.lookAndFeel + component + "/style.css");
	},

	loadStyle : this.loadStyleForComponent,

	/**
	 * Get the path of the component
	 * @return The path of the component specified (String)
	 * @param component (String)
	 */
	getComponentPath : function(component){
		return syslib.path + "components/" + syslib.lookAndFeel + component + "/";
	}
};

/**
 * Aliases and extensions for syslib class
 */
__debug		= syslib.debug;
__options 	= syslib.options;

/**
 * The element manipulation class
 * @class syslib.element
  * @static
 */
syslib.element = {
	innerAttributes : null,

	getById : function(id){
		return (typeof id === 'object') ? id : document.getElementById(id);
	},
	
	generateID : function(){
		return "syslib_generated_id-" + (Math.random() * 10000);
	}, 

	createFromJSON : function(parent, nodeContent){
		var node;
		for(var i = 0; i < nodeContent.length;i++){
			if(nodeContent[i] === undefined || nodeContent[i] === null){
				syslib.messages.warning("syslib.element.createFromJSON(): Impossible to draw an undefined element!");
			} else if(__valid(nodeContent[i].tagName)){
				node = nodeContent[i];
			} else if(i === 0 && nodeContent[i].constructor == String){ /* Root node */
				node = document.createElement(nodeContent[i]);
				if(!syslib.util.valid(parent)){
					this.innerAttributes = {};
				}
			} else if(nodeContent[i].constructor == Object){ /* Attributes */
				for(attribute in nodeContent[i]){
					if(nodeContent[i][attribute] === false){
						continue;
					}
					if(attribute.toLowerCase() != "innername"){
						node.setAttribute(attribute, nodeContent[i][attribute]);
					}

					if(attribute == "class") {
						node.className = nodeContent[i][attribute];
					} else if(attribute == "style") {
						node.style.cssText = nodeContent[i][attribute];
					} else if(attribute == "cellpadding"){
						node.cellPadding = nodeContent[i][attribute];
					} else if(attribute == "cellspacing"){
						node.cellSpacing = nodeContent[i][attribute];
					} else if(attribute == "colspan"){
						node.colSpan = nodeContent[i][attribute];
					} else if(attribute == "rowspan"){
						node.rowSpan = nodeContent[i][attribute];
					} else if(attribute == "innerName"){
						this.innerAttributes[nodeContent[i][attribute]] = node;
					} else if(attribute.indexOf("on") != -1){ // for all events
						node[attribute] = new Function(nodeContent[i][attribute]);
					}
				}
			} else if (nodeContent[i].constructor == Array){ /* Child nodes */
				this.createFromJSON(node, nodeContent[i]);
			} else if(i !== 0 && nodeContent[i].constructor == String){ /* Content */
				node.innerHTML += nodeContent[i];
			}
		}
 
		if(__valid(parent)){ parent.appendChild(node); }

		return { element : node, references : this.innerAttributes };
	},

	hide : function(element){
		try{
			element = __id(element);
			element.style.display = 'none';
		} catch(e){
			syslib.messages.error("syslib.element.hide(): Error while trying to hide the element: " + e.message);
		}
			
	},

	show : function(element){
		try{
			element = __id(element);
			element.style.visibility = '';
			element.style.display = '';
		} catch(e){
			syslib.messages.error("syslib.element.show(): Error while trying to show the element: " + e.message);
		}
	},

	isVisible : function(element){
		element = __id(element);
		style	= element.style;

		if(!__valid(element)){ return false; }
		if(!__valid(style)){ return true; }

		if(style.display != "none" && style.visibility != "hidden"){
			if(element.parentNode){
				return this.isVisible(element.parentNode);
			} else {
				return true;
			}
		} else {
			return false;
		}
	},

	getDimensions : function(element){
		element = __id(element);
		return {width: element.offsetWidth, height: element.offsetHeight};
	},

	toggleVisibility : function(element){
		if(this.isVisible(element)){ this.hide(element); } else { this.show(element); }
	},

	update : function(element, value){
		value 	= (!syslib.util.valid(value)) ? '' : value;
		element = __id(element);

		element.innerHTML = value;
	},

	updateStyle : function(element, style){
		element = __id(element);
		if(__valid(element) && __valid(style)){
			for(var name in style){
				var value = style[name];
				element.style[name] = value;
			}
		}
	}
};

/**
 * Aliases and extensions for element class
 */
__id 		= syslib.element.getById;
Element 	= syslib.element;


/**
 * Syslib utilities class
 * @class syslib.util
 * @author Gabriel Ricci
 * @static
 */
syslib.util = {
	isIE : function(){
		return (navigator.appName.indexOf('Internet Explorer') > -1) ? true : false;
	},

	isNetscapeCompatible : function(){
		return (navigator.appName.indexOf('Netscape') > -1) ? true : false;
	},

	fromKeyCode : function(code){
		if(this.isIE()){
			switch(code){
				case 96: 	return 0;
				case 97: 	return 1;
				case 98: 	return 2;
				case 99: 	return 3;
				case 100: 	return 4;
				case 101: 	return 5;
				case 102: 	return 6;
				case 103: 	return 7;
				case 104: 	return 8;
				case 105: 	return 9;
				default: 	return String.fromCharCode(code);
			}
		} else {
			return String.fromCharCode(code);
		}
	},

	valid : function(elem){
		return (elem === undefined || elem === null || elem === false || elem === "") ? false : true;
	},

	emptyFunction : function(){},

	sleep : function(secs){
		var then = new Date(new Date().getTime() + secs);
		while (new Date() < then) {
			//NOTHING, JUST WAIT
		}
		delete then;
	}
};

/**
 * Aliases and extensions for util class
 */
__valid			= syslib.util.valid;
__emptyFunc	= syslib.util.emptyFunction;

/**
 * DOM navigation class
 * @class syslib.dom
 * @author Gabriel Ricci
 * @static
 */
syslib.dom = {
	/**
	 * @private
	 */
	__navigator : function(element, search){
		element 	= __id(element);
		var parent	= element.parentNode;
		var childs 	= [];

		if(!__valid(parent)){
			childs	= [];
		} else {
			childs = parent.childNodes;
		}

		for(var i = 0; i < childs.length; i++){
			var child = childs[i];
			if(child === element){
				var index = i;
				var returnChild = null;
				switch(search){
					case "next":
						index++;
						returnChild = childs[index];
						return (syslib.util.valid(returnChild )) ? returnChild : false;

					case "previous":
						index--;
						returnChild = childs[index];
						return (syslib.util.valid(returnChild )) ? returnChild : false;

				}
			}
		}
	},

	next : function(element){
		return this.__navigator(element, 'next');
	},

	previous : function(element){
		return this.__navigator(element, 'previous');
	}
};

/**
 * The object class
 * @class syslib.object
 * @author Gabriel Ricci
 * @static
 */
syslib.object = {
	createClass : function(baseClass, src){
		// create the class
		function newClass(){
			if(typeof this.__construct === 'function'){
				this.__construct.apply(this, arguments);
			} else {
				__emptyFunc.apply(this, arguments);
			}
		}
	
		// create the class source
		var classSource = {};
		
		// extends the superclass, if there's one
		if(__valid(baseClass) && typeof baseClass === 'object'){ 
			classSource = syslib.object.extend(classSource, baseClass);
		}
		
		// check if there's a source passed
		if(__valid(src) && typeof src === 'object'){ 
			classSource = syslib.object.extend(classSource, src);
		}

		// add some magic methods
		classSource = syslib.object.extend(classSource, {
			addProperty : function(type, name, value){
				syslib.object.addProperty(this, type, name, value);
			}
		});
		
		// set the prototype
		newClass.prototype = classSource;

		// static methods
		newClass.extend = function(sourceObj){
			syslib.object.extend(newClass.prototype, sourceObj);
		};
		
		return newClass;
	},

	extend : function(destinyObj, sourceObj){
		if(!syslib.util.valid(sourceObj)) { return destinyObj; }
		if(!syslib.util.valid(destinyObj)) { return sourceObj; }

		for(var propertyOrMethod in sourceObj){
			destinyObj[propertyOrMethod] = sourceObj[propertyOrMethod];
		}

		return destinyObj;
	},
	
	clone : function(src){
		// if the source isn't an object, just return it as it is
		if(typeof src != "object" || !__valid(src)){
			return src;
		}
		
		// clone the constructor
		var cloned = new src.constructor();
		
		// set the values
		for(var item in src){
			cloned[item] = syslib.object.clone(src[item]);
		}
		
		return cloned;
	}, 
	
	serialize : function(object){
		var serialized = "";
		for(var i in object){
			serialized += "&" + i + "=" + object[i];
		}
		
		return serialized;
	}, 
	
	addProperty : function(object, type, name, value){
		if(!__valid(name) || typeof type !== "string"){
			syslib.messages.warning("Trying to add an invalid property to the object!");
			return false;
		}

		if(typeof value !== type){
			syslib.messages.warning("Property " + name + " must be of type " + type + "!");
			return false;
		}

		object[name] = value;

		var functionName = name.charAt(0).toUpperCase() + name.substring(1, name.length);

		var getFunc = function(){
			return this[name];
		};

		var setFunc = function(newValue) {
			if (typeof value !== type) {
			   syslib.messages.warning("Property " + name + " must be of type " + type + "!");
			   return false;
			}

			var oldValue = object[name];
			var event = {
				propertyName: name,
			    propertyOldValue: oldValue,
			    propertyNewValue: newValue,
			    returnValue: true
			};

			if(typeof this.__set === 'function'){ this.__set(event); }
			if (event.returnValue){ this[name] = event.propertyNewValue;}
		};

		object["get" + functionName] = function(){return getFunc.apply(object, arguments);};
		object["set" + functionName] = function(){return setFunc.apply(object, arguments);};
	} 
};

/**
 * Alias for the syslib.object.newClass function 
 * @alias
 */
__class = syslib.object.createClass;

/**
 * The functions class
 * @class syslib.functions
 * @author Gabriel Ricci
 * @static
 */
syslib.functions = {
	applyTo : function(method, object){
		return function(){
			return method.apply(object, arguments);
		};
	},
	
	/**
	 * @private
	 */
	__prototype : {
		applyTo : function(object){
			if(!__valid( object.isApplyTo)){
				return syslib.functions.applyTo(this, object);
			}
		}
	}
};

/**
 * Aliases and extensions for functions class
 */
syslib.object.extend(Function.prototype, syslib.functions.__prototype);

/**
 * Event manipulation class
 * @class syslib.event
 * @author Gabriel Ricci
 * @static
 */
syslib.event = {
	getElement : function(evt){
		if(syslib.util.isIE()){
			return window.event.srcElement;
		} else {
			return evt.target;
		}
	},

	getKeyCode : function(evt){
		return window.event ? window.event.keyCode : evt.which;
	},

	isSpecialCode : function(evt){
		var code	= this.getKeyCode(evt);
		var special = false;
		var scodes 	= [8, 13, 36, 35, 46, 0, 45, 33, 34, 9, 16, 17, 18, 37, 38, 39, 40];

		for(var i in scodes){
			var scode = scodes[i];
			if(scode == code){
				special = true;
			}
		}

		return special;
	},

	listen : function(eventName, element, observer, useCapture){
		if(!__valid(element)){
			syslib.messages.error("Element invalid for event " + eventName);
			return false;
		}

		useCapture = useCapture || false;
		if (element.addEventListener) {
			element.addEventListener(eventName, observer, useCapture);
	    } else if (element.attachEvent) {
			element.attachEvent('on' + eventName, observer);
	    }
	},
	
	stopPropagation : function(event){
		if (event.preventDefault) {
      		event.preventDefault();
      		event.stopPropagation();
    	} else {
      		event.returnValue = false;
      		event.cancelBubble = true;
    	}
	},
	
	stopListening : function(){
		syslib.messages.info("syslib.event.stopListening(): This function is not implemented yet!");
	},

	isLeftClick: function(event) {
    	return (((event.which) && (event.which == 1)) ||
         	   ((event.button) && (event.button == 1)));
	},

	mouseX: function(event) {
		return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
	},

	mouseY: function(event) {
		return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
	}
};


/**
 * The string class
 * @class syslib.string
 * @author Gabriel Ricci
 * @static
 */
syslib.string = {
	REPLACE_TYPE_ONE : "REPLACE_TYPE_ONE",
	REPLACE_TYPE_ALL : "REPLACE_TYPE_ALL",
	REPLACE_DIRECTION_TOPBOTTOM : "REPLACE_DIR_TB",
	REPLACE_DIRECTION_BOTTOMTOP: "REPLACE_DIR_BT",

	pad : function(str, length, padWith){
		if(str.length >= length){
			return str;
		}

		if(typeof str !== 'string'){
			str = str.toString();
			if(typeof str !== 'string'){
				return str;
			}
		}

		var appendString = "";
		var neededLength = length - str.length;

		for(var i = 1; i <= neededLength; i++){
			appendString = padWith + appendString;
		}

		str = appendString + str;
		return str;
	},

	replace : function(needle, replaceWith, str, options){
		options 	= syslib.object.extend({}, options);
		type 		= options.type;
		direction	= options.direction;

		var parts 	= str.split(needle);
		var text		= parts.join(replaceWith);
		
		delete parts;
		return text;
	},

	reverse : function(str){
		var newStr = "";
		for(var i = str.length; i > 0; i--){
			newStr = newStr + str.charAt((i-1));
		}
		return newStr;
	},

	/** 
	 * @private
	 */
	__prototype : {
		strReplace : function(needle, replaceWith, options){
			return syslib.string.replace(needle, replaceWith, this, options);
		},
		pad : function(length, padWith){
			return syslib.string.pad(this, length, padWith);
		},
		reverse : function(){
			return syslib.string.reverse(this);
		}
	}
};

/**
 * Aliases and extensions for string class
 */
// syslib.object.extend(String.prototype, syslib.string.__prototype);

/**
 * Syslib math class
 * @class syslib.object
 * @author Gabriel Ricci
 * @static
 */
syslib.math = {
	toNegative : function(number){
		if(number < 0){
			return number;
		} else {
			return number * -1;
		}
	}
};

/**
 * Aliases and extensions for math class
 */
syslib.object.extend(Math, syslib.math);

/**
 * The array class
 * @class syslib.array
 * @author Gabriel Ricci
 * @static
 */
syslib.array = {
	clone : function(array){
		var newArray = [];
		for(var i = 0; i < array.length; i++){
			newArray[i] = array[i];
		}
		return newArray;
	}
};


/**
 * The form class
 * @class syslib.form
 * @author Gabriel Ricci
 * @static
 */
syslib.form = {
	validate : function(form, nrf, options){
		// format the options
		if(typeof options == "boolean"){ options = {}; }
		var options = syslib.object.extend({
			onlyVisible : true,
			showErrorFields : false 
		}, options);
		
		// create the required variables
		var checks = [];
		var radios = [];
		var elements = [];
		var nr = ( typeof nrf == 'string' ) ? nrf : "";

		// search for elements in the form
		for(var i=0;i<form.elements.length;i++){
			var element = form.elements[i];
			
			// verify if the element is required in the validation
			if(element.getAttribute("_required") == "false" || element.getAttribute("_required") == false){
				continue;
			}

			// verify the value of the element
			if(element.value === ""){
				// verify if the element is required
				if(nr.indexOf(element.name) == -1){
					// verify if the element is disabled or read-only
					if(element.disabled !== true && element.readOnly !== true){
						// verify if the validation includes invisible fields
						if(__valid(options.onlyVisible) && options.onlyVisible == true){
							 if(!syslib.element.isVisible(element)){ continue; }
						}
						
						// log the error
						syslib.messages.warning("syslib.form.validate(): The field " + element.name + " is invalid for the form!");
						
						// return
						return false;
					}
				}
			// checkbox
			} else if(element.type == 'checkbox'){
				// verify if the validation includes invisible fields
				if(__valid(options.onlyVisible) && options.onlyVisible == true){
					 if(!syslib.element.isVisible(element)){ continue; }
				}
				var newName = element.name;
				if(newName.indexOf('[]') != -1){
					newName = newName.replace("[]", "");
					if(!syslib.util.valid(checks[newName]) || checks[newName] === false){
						checks[newName] = element.checked;
						elements[newName] = element;
					}
				}
			// radio
			} else if(element.type == "radio"){
				// verify if the validation includes invisible fields
				if(__valid(options.onlyVisible) && options.onlyVisible == true){
					 if(!syslib.element.isVisible(element)){ continue; }
				}
				var name = element.name;
				if(!syslib.util.valid(radios[name]) || radios[name] === false){
					radios[name] = element.checked;
					elements[name] = element;
				}
			}
		}
		
		// verify the checkboxes
		for(check in checks){
			if(checks[check] === false){
				if(nr.indexOf(check) == -1){
					return false;
				}
			}
		}
		
		// verify the radios
		for(radio in radios){
			if(radios[radio] === false){
				if(nr.indexOf(radio) == -1){
					return false;
				}
			}
		}
		
		// return
		return true;
	},

	serialize : function(form){
		var elements 	= form.elements;
		var parts		= [];

		for(var i = 0; i < elements.length; i++){
			var element = form.elements[i];
			if(element.disabled){continue;}
			var name = (syslib.util.valid(element.name)) ? encodeURIComponent(element.name) : false;
			if(!__valid(name)){continue;}

			if(element.type === 'checkbox'){
				if(element.name.indexOf("[]") != -1){
					value = (element.checked === true ? element.value : false);
				} else {
					value = (element.checked === true ? "on" : "off");
				}
				if(__valid(value)){parts.push(name + '=' + value);}
				continue;
			}
			
			if(element.type === "radio"){
				value = (element.selected === true || element.checked === true) ? element.value : false;
				if(__valid(value)){parts.push(name + '=' + value);}
				continue;
			}
			
			if (element.tagName.toLowerCase() === "select"){
				for(var c = 0; c < element.options.length; c++){
					var option = element.options[c];
					if(!option.selected){continue;}
					value = (__valid(option.value)) ? encodeURIComponent(option.value) : false;
					if(__valid(value)){parts.push(name + '=' + value);}
				}
				continue;
			}

			value = (element.value !== undefined) ? encodeURIComponent(element.value) : element.name;
			if(__valid(value)){parts.push(name + '=' + value);}
		}

		return parts.join("&");
	}
};

/**
 * Aliases and extensions for math class
 */
Form = syslib.form;

/**
 * XML parsing class
 * @class syslib.ui.xml
 */
syslib.xml = {
	createFromText : function(text){
		try {
			// ie
			var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async="false";
			xmlDoc.loadXML(text);
			
			return xmlDoc;
		} catch(e) {
	  		try {
	  			// firefox / opera / etc
			    var parser = new DOMParser();
			    return parser.parseFromString(text,"text/xml");
			} catch(e) {
				syslib.messages.error("syslib.xml.createFromText(): You browser doesn't support dynamic XML creation!");
				return false;
			}
		}
	}, 
	
	convertXmlToHTML : function(xmlNode){
		// get the tagname
		var tagName = xmlNode.tagName
		
		// create the element
		var element = document.createElement(tagName);
		
		// get the attributes
		var attributes = this.convertAttributesToObject(xmlNode.attributes);
		
		// search the attributes
		for(var attribute in attributes){
			element.setAttribute(attribute, attributes[attribute]);
		}
		
		return element;
	},  
	
	convertXmlToText : function(xmlNode){
		var text = "";
		// check 
		if(xmlNode.nodeType == 1 && __valid(xmlNode.tagName)){
			// create the tag
			text += "<" + xmlNode.tagName + " ";
			
			// get the attributes
			var attributes = xmlNode.attributes;
			
			// search the attributes
			for(var i = 0; i < attributes.length; i++){
				// get the attribute
				attribute = attributes[i];
			
				// convert
				text += attribute.name + "=\"" + attribute.value  + "\" ";
			}
			
			// close the tag
			text += ">";
			
			// search the childs
			for(var i = 0; i < xmlNode.childNodes.length; i++){
				// convert the child
				text += this.convertXmlToText(xmlNode.childNodes[i]);
			}
			
			// close the tag
			text += "</" + xmlNode.tagName + ">";
		} else {
			// text node, just get the value
			text += xmlNode.nodeValue;
		}
		
		return text;
	}, 
	
	innerHTML : function(xmlNode){
		// create the variables
		var text = "";
		
		// search the child nodes
		for(var i = 0; i < xmlNode.childNodes.length; i++){
			// get the child
			var child = xmlNode.childNodes[i];
			
			// convert
			text += this.convertXmlToText(child);
		}
		
		// return
		return text;
		
	}, 
	
	convertAttributesToObject : function(domAttributesList){
		// create the storage object
		var attributes = {};
		
		// search for attributes
		for(var i = 0; i < domAttributesList.length; i++){
			// get the attribute
			var attributeNode = domAttributesList[i];
			
			// set the data
			attributes[attributeNode.name] = attributeNode.value;
		}
		
		return attributes;
	}
};

/**
 * Exceptions namespace
 * @namespace syslib.exceptions
 */
syslib.exceptions = {};

/**
 * Basic syslib exception class
 * @class syslib.ui.exceptions.Exception
 */ 
syslib.exceptions.Exception = __class();
syslib.exceptions.Exception.prototype = {
	__className : "syslib.exception.Exception", 
	message : null,
	 
	__construct : function(message){
		this.__className = "syslib.exception.Exception";
		this.message = message;
	} 
};

/**
 * Used when a file was not been loaded yet
 * @class syslib.exceptions.FileNotLoadedException
 */
 syslib.exceptions.FileNotLoadedException = __class();
 syslib.exceptions.FileNotLoadedException.prototype = {
 	__className : "syslib.exception.FileNotLoadedException",
 	message : null,  
 	file : null, 
 	
 	__construct : function(file){
 		this.__className = "syslib.exception.FileNotLoadedException";
 		this.file = file;
		this.message = "The file " + file + " was not been loaded yet";
	}
};

/**
 * Used when a file was not been found
 * @class syslib.exceptions.FileNotFoundException
 */
 syslib.exceptions.FileNotFoundException = __class();
 syslib.exceptions.FileNotFoundException.prototype = {
 	__className : "syslib.exception.FileNotFoundException",
 	message : null,  
 	file : null, 
 	
 	__construct : function(file){
 		this.__className = "syslib.exception.FileNotFoundException";
 		this.file = file;
		this.message = "The file " + file + " was not been found";
	}
}; 

/**
 * The tag library class, which is responsable for handle parse requests and forward it to a parser
 * @class syslib.taglib
 * @author Gabriel Ricci
 * @static
 */
syslib.taglib = {
	MAX_LOAD_TRIES : 25, // in milliseconds, MAX_LOAD_TRIES * 1000

	TYPE_BASIC : "BASIC_TAG", 
	TYPE_VISUAL : "VISUAL_TAG", 
	
	tags : {},
	temporaryStorage : [],
	
	__onParseBodyListeners : [],

	registerTag : function(tag, options){
		// format the options
		options = syslib.object.extend({
			innerContent : true
		}, options);

		// create the specification
		if(__valid(options.packageName) && __valid(options.parser) && typeof tag == 'string'){
			var spec = {
				tagName : tag,
				packageName : options.packageName,
				parser	: options.parser,
				innerContent : (options.innerContent === false) ? false : true,
				lastParser : null
			};

			// register
			this.tags[tag] = spec;
			
			// create an empty element (workaround for internet explorer)
			var tagElement = document.createElement(tag);
			
			// delete unused variables
			delete tagElement;
			delete spec;
		} else {
			syslib.messages.error('syslib.taglib.registerTag(): Invalid specification for tag ' + tag);
		}
	},

	isRegistered : function(tag){
		return __valid(this.tags[tag]);
	},

	parseAndAppend : function(text, container){
		// log
		syslib.messages.info("syslib.taglib.parseBody(): Parsing a block");
		
		// create the parser
		var parser = new syslib.taglib.parser2(text, __id(container), syslib.taglib.parser2.INSERT_MODE_INSIDE);
		
		// delete the parser
		delete parser;
		
	},
	parseBody : function(){
		// log
		syslib.messages.info("syslib.taglib.parseBody(): Parsing body");
	
		// get the script elements
		var scriptElements = document.body.getElementsByTagName("script");

		// search the scripts
		for(var i = 0; i < scriptElements.length; i++){
			// get the script
			var script = scriptElements[i];
			var type 	= script.getAttribute("type");
			
			// check if the script is a syslib code
			if(__valid(type) && type.toLowerCase() == "application/syslib+xml"){
				// create the parser
				var parser = new syslib.taglib.parser2(script.innerHTML, script, syslib.taglib.parser2.INSERT_MODE_BEFORE);
				
				// delete the parser
				delete parser;
			}
		}
		
		// call the event handlers
		for(var i = 0; i < this.__onParseBodyListeners.length; i++){
			// get the handler
			var handler = this.__onParseBodyListeners[i];
			
			// check the type
			if(__valid(handler) && typeof handler == "function"){
				// call
				handler();
			}
		} 
		
	},
	onParseBody : function(callback){
		this.__onParseBodyListeners.push(callback);
		delete callback;
	}
};

/** 
 * The new tag library parser
 * @class syslib.taglib.parser2
 * @author Gabriel Ricci
 * @since 0.5.3
 */
syslib.taglib.parser2 = __class();
syslib.taglib.parser2.prototype = {
	root : null,
	container : null, 
	mode : null,  
	loadAttempts : null, 
	conversors : null, 
	 
	__construct : function(content, container, mode){
		// set the needed variables
		this.mode = syslib.taglib.parser2.INSERT_MODE_INSIDE;
		this.loadAttempts = {};
		
		// create the root container
		this.root = syslib.xml.createFromText("<root>" + content + "</root>"); 
		
		// set the mode, if it's valid
		if(__valid(mode)){
			this.mode = mode;
		}
		
		// set the container
		if(!__valid(container)){
			this.container = document.createElement("span");
		} else {
			this.container = container;
		}
		
		// parse the tags
		this.parseTree();
	}, 
	
	parseTree : function(){
		// get the root element
		var root = this.root.childNodes[0];
		
		// search the nodes
		while(root.childNodes.length > 0){
			// erase the conversors list
			this.conversors = [];
		
			// get the current node
			var node = root.childNodes[0];

			try{
				// create a root for this element
				var localRoot = document.createElement("span");
			
				// parse the tag
				this.parseXMLTree(node, localRoot);
				
				// append
				if(this.mode == syslib.taglib.parser2.INSERT_MODE_BEFORE){
					this.container.parentNode.insertBefore(localRoot.childNodes[0], this.container);
				} else {
					this.container.appendChild(localRoot.childNodes[0]);
				}
				
				// search the conversors to call the onEnterBody event
				for(var c = 0; c < this.conversors.length; c++){
					// get the conversor
					var conversor = this.conversors[c];
					
					// call the event handler
					if(__valid(conversor.onEnterBody) && typeof conversor.onEnterBody == "function"){
						conversor.onEnterBody();
					}
				}
				
				// delete this node
				root.removeChild(node);
			} catch(e){
				if(e instanceof syslib.exceptions.FileNotLoadedException){
					// log the error message
					syslib.messages.warning("syslib.taglib.parser2.parseTree(): This execution failed to parse some tags, scheduling another one!");
					
					// schedule a new execution
					setTimeout(this.parseTree.applyTo(this), 100);
					return false;
				} else if(e instanceof syslib.exceptions.FileNotFoundException){
					// log the error message
					syslib.messages.error("syslib.taglib.parser2.parseTree(): Some required files have not been found, this parser can't continue!");
					return false;
				} else {
					// log the error message
					syslib.messages.error("syslib.taglib.parser2.parseTree(): Fatal error: " + e.message + " ( "+e.file + " - line " + e.line + " ) - Please report this error in http://syslibjs.googlecode.com/");
				}
			}
		}
	}, 
	
	parseXMLTree : function(xmlNode, container){
		// create the needed variables
		var createdElement = null;
		
		// check if the node is an element
		if(xmlNode.nodeType != 1){
			if(syslib.util.isIE()){
				// on ie, appendChild throws an exception, so we get the innerHTML and set it on the container
				container.innerHTML = syslib.xml.innerHTML(xmlNode.parentNode);
			} else {
				// append to the html and return
				container.appendChild(xmlNode.cloneNode(true));
			}
			
			// retorna
			return true;
		}
		
		try{
			// get the tag name
			var tagName = xmlNode.tagName.toLowerCase();
		} catch(e){
			container.appendChild(xmlNode.cloneNode(true));
		}
		
		// parse
		if(this.isCustomTag(tagName)){
			// non-standard tag, try to convert it
			conversor = this.parseCustomTag(xmlNode, tagName);
			
			if(__valid(conversor)){
				// get the created element
				createdElement = conversor.__element;
				
				// append to the container
				container.appendChild(createdElement);
				
				// search for child nodes
				if(createdElement.hasChildNodes){
					for(var i = 0; i < createdElement.childNodes.length; i++){
						// get the children
						var children = createdElement.childNodes[i];
						
						// parse this custom tag until reach the element xmlNode.childNodes[0], when found 
						// this element, the parse get back to normal
						this.parseHTMLTree(children, xmlNode.childNodes);
					}
				}
			}
		} else {
			// convert the xml tag to an html tag
			createdElement = syslib.xml.convertXmlToHTML(xmlNode);
			
			// append to the html tree
			container.appendChild(createdElement);
			
			// search for child nodes
			if(xmlNode.hasChildNodes){
				for(var i = 0; i < xmlNode.childNodes.length; i++){
					// get the children
					var children = xmlNode.childNodes[i];
					
					// parse
					this.parseXMLTree(children, createdElement);
				}
			}
		}
	}, 
	
	parseHTMLTree : function(htmlNode, xmlChildNodes){
		// create the needed variables
		var createdElement = null;
	
		// check if this node is the limiter
		if(htmlNode.nodeType != 1 && htmlNode.nodeValue == syslib.taglib.parser2.PARSER_LIMITER){
			// get the container
			var htmlContainer = htmlNode.parentNode;
		
			// remove this limiter
			htmlContainer.removeChild(htmlNode);
		
			// restore the parse process in xml mode
			for(var i = 0; i < xmlChildNodes.length; i++){
				this.parseXMLTree(xmlChildNodes[i], htmlContainer);	
			}
		} 
		
		// check if the node is an element
		if(htmlNode.nodeType != 1 || !__valid(htmlNode.tagName)){
			// not an element, just return
			return true;
		}
		
		// get the tag name
		var tagName = htmlNode.tagName.toLowerCase();
		
		// parse
		if(this.isCustomTag(tagName)){
			// non-standard tag, try to convert it
			conversor = this.parseCustomTag(htmlNode, tagName);
			
			if(__valid(conversor)){
				// get the created element
				createdElement = conversor.__element;
				
				// append to the container
				htmlNode.parentNode.replaceChild(createdElement, htmlNode);
				
				// search for child nodes
				if(createdElement.hasChildNodes){
					for(var i = 0; i < createdElement.childNodes.length; i++){
						// get the children
						var children = createdElement.childNodes[i];
						
						// parse this custom tag until reach the element htmlNode.childNodes[0], when found 
						// this element, the parse get back to normal
						this.parseHTMLTree(children, htmlNode);
					}
				}
			}
		} else {
			// normal element, just parse the childs
			createdElement = htmlNode;
			
			// search for child nodes
			if(htmlNode.hasChildNodes){
				for(var i = 0; i < htmlNode.childNodes.length; i++){
					// get the children
					var children = htmlNode.childNodes[i];
					
					// parse
					this.parseHTMLTree(children, xmlChildNodes);
				}
			}
		}
	}, 
	
	parseCustomTag : function(myNode, tagName){
		// get the tag specification
		var tagSpecification = syslib.taglib.tags[tagName];
	
		try{
			// try to create the conversor
			var conversor = eval("new " + tagSpecification.parser + "()");
		} catch(e){
			// shows an error message
			syslib.messages.warning("syslib.taglib.parser2.convertCustomTag(): Couldn't find/load the parser for the tag " + tagName + "!");
		
			// check if the parser is valid or the max number of errors was reached
			if(__valid(this.loadAttempts[tagName]) && this.loadAttempts[tagName] >= syslib.taglib.MAX_LOAD_TRIES){
				// shows an error message and throws an exception
				syslib.messages.error("syslib.taglib.parser2.convertCustomTag(): The tag " + tagName + " has reached the maximum number of load attempts!");
				throw new syslib.exceptions.FileNotFoundException("[tag " + tagName + " classfiles]");
			} else {
				if(!__valid(this.loadAttempts[tagName])){
					// load process not started, load the class files
					syslib.io.importClass(tagSpecification.packageName, {
						onComplete : function(filename){
							syslib.messages.info("syslib.taglib.parser2.convertCustomTag(): File loaded: " + filename);
						}
					});
					
					// set the number of load attempts
					this.loadAttempts[tagName] = 0;
				} else {
					// increase the number of load attempts
					this.loadAttempts[tagName]++
				}
				
				// throws an exception
				throw new syslib.exceptions.FileNotLoadedException("[tag " + tagName + " classfiles]");
			}
		}
		
		// update the required definitions
		conversor.__attributes 	= syslib.xml.convertAttributesToObject(myNode.attributes);
		conversor.__innerHTML	= syslib.taglib.parser2.PARSER_LIMITER;
		
		// setting this conversor as the last parser for this tag
		syslib.taglib.tags[tagName].lastParser = conversor;
		
		// set the parent custom tag, if needed
		if(__valid(conversor.__parentTagName)){
			// check if the tag parent is available an is parsed
			if(__valid(syslib.taglib.tags[conversor.__parentTagName])){
				// sets the parsed parent on this tag
				conversor.__parent = syslib.taglib.tags[conversor.__parentTagName].lastParser;
			} else {
				// invalid parent, shows a warning
				syslib.messages.warning("syslib.taglib.parser2.convertCustomTag(): Couldn't find a suitable parent for tag " + tagName + ", skipping...");
				return false;
			}
		}
		
		// execute
		conversor.prepare();
		conversor.execute();
		conversor.finalize();
		
		// store this conversor
		this.conversors.push(conversor);
		
		return conversor;
	}, 
	
	isCustomTag : function(tagName){
		// check the integrity
		if(!__valid(tagName)){
			return false;
		}
		
		// search the custom tags
		for(var tag in syslib.taglib.tags){
			if(tagName.toLowerCase() == tag.toLowerCase()){
				return true;
			}
		}
		
		// no custom tags found, return false
		return false; 
	}	
};

syslib.taglib.parser2.INSERT_MODE_INSIDE = 0, 
syslib.taglib.parser2.INSERT_MODE_BEFORE = 1,

syslib.taglib.parser2.PARSER_LIMITER = "#syslib.taglib.parser2.PARSER_LIMITER#";

/**
 * The general message class for debugging
 * @class syslib.message
 */
syslib.message = __class();
syslib.message.prototype = {
	message : null, 
	tag : null, 
	color : null, 
	createDate : null, 

	/**
	 * @constructor
	 * @param {String} message
 	 * @param {String} tag
	 */
	__construct : function(message, tag) {
		this.message = message;
		this.tag = tag;
		this.color = this.getColorForTag(tag);
		this.createDate = syslib.date.make("h:i:s");
    },

	getColorForTag : function(tag){
		if(tag === 'error'){
			return 'red';
		} else if(tag === 'warning'){
			return 'yellow';
		} else if(tag === 'info'){
			return 'green';
		} else {
			return 'white';
		}
	}
};

/**
 * The static messages class that control all messages
 * @class syslib.messages
 * @author Gabriel Ricci
 * @static
 */
syslib.messages = {
	entries : [],

	add : function(message, tag){
		if(!syslib.debug){return false;}
		var entry = new syslib.message(message, tag || "generic-message");
		this.entries.push(entry);
		if(syslib.console.element !== null){ syslib.console.updateEntries(); }
	},

	clear : function(){
		this.entries = [];
		if(syslib.console.element !== null){ syslib.console.updateEntries(); }
	},

	error : function(message){
		this.add(message, 'error');
	},

	warning : function(message){
		this.add(message, 'warning');
	},

	info : function(message){
		this.add(message, 'info');
	},

	getEntries : function(){
		return syslib.array.clone(this.entries);
	}
};

/**
 * The console class
 * @class syslib.console
 * @author Gabriel Ricci
 * @static
 */
syslib.console = {
	id : 'syslib_logger',
	console : null,
	entries : null,
	command : null,
	opener  : null,

	bottomPos : 0,
	leftPos : 0,

	positionTimer : null,

	createConsole : function(){
		try{
			syslib.loadStyleForComponent('console');

			objson = ["div", {'class' : 'console-main', 'id' : this.id, 'innerName' : 'main'},
						["form", {"name" : 'console_form', "id" : "console_form"},
							["table", {"width" : "100%", "border" : "0", "cellpadding" : "0", "cellspacing" : "0", "class" : "console-top"},
								["tbody",
									["tr",
										["td", {"width" : "40%", "id" : "console_title"},
											"System library version " + syslib.version + " console"
										],
										["td", {"align" : "right", "width" : "60%", "id" : "console_buttons"},
											["input", {"type" : "text", "id" : "console_command", "size" : "60", "class":"console-command"}],
											"&nbsp",
											["input", {"type" : "submit", "id" : "console_run", "value" : "Run", "class":"console-button", "onclick" : "syslib.console.runCommand(); return false;"}],
											"&nbsp",
											["input", {"type" : "button", "id" : "console_close", "value" : "Close", "class":"console-button", "onclick" : "syslib.console.close()"}]
										]
									]
								]
							]
						],
						["div", {"innerName" : "entries", "class" : "console-entries"}]
					];

			openerjson = ["div", {"class" : 'console-open', 'id' : 'console-opened', 'align' : 'center'},
						 	["a", {"href" : "javascript:void(0);", "innerName" : 'opener'},
								"Toggle console"
							]
						 ];

			this.console = syslib.element.createFromJSON(false, objson);
			this.opener = syslib.element.createFromJSON(false, openerjson);

			document.body.appendChild(this.console.element);
			document.body.appendChild(this.opener.element);

			this.entries = this.console.references.entries;
			this.command = __id('console_command');

			syslib.event.listen('click', this.opener.references.opener, function(){syslib.console.toggle();});
			syslib.event.listen('click', __id('console_close'), function(){syslib.console.close();});
			syslib.event.listen('submit', __id('console_form'), function(evt){syslib.console.runCommand(); syslib.event.stopPropagation(evt);});

			this.close();
		} catch(e){
			alert("ERROR: Could not start the console system: " + e.message);
		}
    },

	runCommand : function(){
		var command = this.command.value;
		try{
			if(command === 'clear'){
				syslib.messages.clear();
			} else if(command === 'help'){
				var help = 'The commands are: <br /><br />  - clear: clear the console<br />  - help: show this message<br />  - close: close the console';
				syslib.messages.add(help, 'help');
			} else if(command === 'close'){
				syslib.console.close();
			} else {
				eval(command);
			}
		} catch(e){
			syslib.messages.error("System could not execute the command ["+command+"] - reason: " + e.message);
			this.command.value = '';
			return false;
		}
		syslib.messages.info("Command ["+command+"] executed with success!");
		this.command.value = '';
		return true;
	},

    setPosition : function() {
		try{
			if(!syslib.util.isIE()){
				this.console.element.style.position = "fixed";
				this.console.element.style.left = "0";
				this.console.element.style.bottom = "0";
			} else {
				var pageSize = document.documentElement.offsetHeight;
				var scrlSize = document.body.scrollTop;
				var topPosit = ((pageSize - 240) + scrlSize) + "px";

				this.console.element.style.left = '0';
				this.console.element.style.top  = topPosit;
			}
		} catch(e){
			syslib.messages.error("Could not set the position of the console, the reason is: " + e.message);
		}
	},

    updateEntries : function(){
		if(!__valid(this.entries)){return false;}
		try{
			syslib.element.update(this.entries, '');
	    	var entries = syslib.messages.getEntries();
			entries.reverse();
			for(var i = 0; i < entries.length; i++){
				var obj = entries[i];
				var color = obj.color;
				var content = document.createElement('font');
				content.color = color;
				content.innerHTML = "" + obj.createDate + " [ " + obj.tag + " ] - " + obj.message;
				content.innerHTML += "<br /><br />";
				this.entries.appendChild(content);
			}
		} catch(e){
			alert("ERROR: Could not update the console system, see the error: " + e.message);
		}
	},

    close : function(){
    	if(!syslib.util.valid(this.console)){ this.createConsole(); }
		clearInterval(this.positionTimer);
		syslib.element.hide(this.console.element);
	},

	open : function(){
    	if(!syslib.util.valid(this.console)){ this.createConsole(); }
		this.setPosition(); this.updateEntries(); syslib.element.show(this.console.element);
		this.positionTimer = setInterval("syslib.console.setPosition()", 200);
	},

	toggle : function(){
		if(!syslib.util.valid(this.console)){ this.createConsole();}
		if(syslib.element.isVisible(this.console.element)){
			this.close();
		} else {
			this.open();
		}
	}
};

/**
 * The profiling class
 * @class syslib.profiling
 * @author Gabriel Ricci
 * @static
 */
syslib.profiling = {
	storage : {},

	runFunction : function(funct, identification, timePart){
		if("hisu".indexOf(timePart) == -1) { return false; }
		if(!__valid(identification) || identification === "") { return false; }

		if(typeof funct == "function"){
			if(syslib.debug === true){
				var start = syslib.date.make(timePart);
				funct();
				var totaltime = syslib.date.make(timePart) - start;
				syslib.messages.info("PROFILING :: " + identification + " :: Code executed in " + totaltime + " " + timePart);
			} else {
				funct();
			}
		} else {
			return false;
		}
	},

	start : function(identification, tPart){
		if("hisu".indexOf(tPart) == -1) { return false; }
		if(!__valid(identification) || identification === "") { return false; }
		if(!syslib.debug){ return false; }

		this.storage[identification] = {
			timePart : tPart,
			start : syslib.date.make(tPart),
			end : false,
			totaltime : false
		};
	},

	end : function(identification){
		if(!__valid(identification) || identification === "") { return false; }
		if(!__valid(this.storage[identification])) { return false; }
		if(!syslib.debug){ return false; }

		var entry = this.storage[identification];

		if(__valid(entry.end) || __valid(entry.totaltime)){ return false; }

		entry.end 		= syslib.date.make(entry.timePart);
		entry.totaltime	= entry.end - entry.start;

		syslib.messages.info("PROFILING :: " + identification + " :: Code executed in " + entry.totaltime + " " + entry.timePart);
	}
};

/**
 * The browser history and controls (back, forward, reload and bookmarks) class
 * @class syslib.history
 * @author Gabriel Ricci
 * @static
 */
syslib.history = {
	currentHash : "",
	working : false,
	interval : false,

	init : function(){
		var ctliframe	= document.createElement("iframe");

		ctliframe.id			= 'ctliframe';
		ctliframe.style.display = 'none';

		document.body.appendChild(ctliframe);

		this.interval = setInterval("syslib.history.checkPage()", 100);
	},
	addEntry : function(container, page){
		this.working = true;

		var hash		= this.createHash(container, page);
		var path		= syslib.path + "controls.html?hash=" + hash;
		var ctliframe	= __id('ctliframe');

		if(!__valid(ctliframe)){
			clearInterval(this.interval);
			this.init();
		}

		if(syslib.util.isIE()){
			ctliframe.src = path;
		}

		location.hash = hash;
		this.currentHash = "#" + hash;
		this.working = false;
	},

	createHash : function(container, page){
		var hash = '';
		if(typeof container == 'string'){
			hash = encodeURIComponent(container + "||" + page);
		} else {
			hash = encodeURIComponent(container.id + "||" + page);
		}

		return hash;
	},

	checkPage : function(){
		if(this.working){
			return true;
		}

		var pageHash = '';
		if(syslib.util.isIE()){
			pageHash = decodeURIComponent(location.hash);
		} else {
			pageHash = location.hash;
		}

		var currHash = decodeURIComponent(this.currentHash);
		if(currHash == pageHash || this.working === true){
			return true;
		} else {
			this.currentHash = encodeURIComponent(pageHash);
			this.load(pageHash);
		}
	},

	load : function(hash){
		var currHash 	= decodeURIComponent(hash);
		var spec 			= currHash.split("||");
		var container 	= spec[0];
		var page			= spec[1];
		container			= container.substr(1, container.length);

		if(!__id(container)){
			return false;
		}

		new syslib.ajax.request(page, {
			destiny : container,
			store : false
		});
	},

	reload : function(){
		this.load(this.currentHash);
	}
};

/**
 * The date class
 * @class syslib.date
 * @author Gabriel Ricci
 * @static
 */
syslib.date = {
	weekStartDay : 0, 
	
	make : function(format, currentTime){
		var now			= (typeof currentTime === 'object' && __valid(currentTime)) ? currentTime : new Date();
		var formatted 	= format;

		var hour 		= syslib.string.pad(now.getHours().toString(), 2, "0");
		var minutes = syslib.string.pad(now.getMinutes().toString(), 2, "0");
		var seconds = syslib.string.pad(now.getSeconds().toString(), 2, "0");
		var millis	= now.getTime().toString();

		var day 		= syslib.string.pad(now.getDate().toString(), 2, "0");
		var month	= syslib.string.pad((now.getMonth() + 1).toString(), 2, "0");
		var fullYear	= now.getFullYear();
		var year 		= now.getYear();
		var week 	= now.getWeekOfYear();
		var weekday		= now.getDay();

		formatted = formatted.replace(/[h]/, hour);
		formatted = formatted.replace(/[i]/, minutes);
		formatted = formatted.replace(/s/, seconds);
		formatted = formatted.replace(/u/, millis);

		formatted = formatted.replace(/d/, day);
		formatted = formatted.replace(/w/, weekday);
		formatted = formatted.replace(/m/, month);
		formatted = formatted.replace(/[Yy]/, fullYear);
		formatted = formatted.replace(/[W]/, week);
		formatted = formatted.replace(/[w]/, weekday);

		return formatted;
	},
	
	getWeekOfYear : function(day){
		// create the first day of year date
		var firstDayOfYear = new Date(day.getFullYear(),0,1);
		
		// calculates the difference (in days) to the start of the year
		var daysDiff = ((day - firstDayOfYear) / 86400000) + 1;
		
		// get the week number calculing the first week of the year as the week that containts the first day of the year
		var week = Math.ceil((daysDiff + firstDayOfYear.getDay())/7);
		
		// return the week number calculing the first week of the year as the week that have the first [weekStartDay] of the year
		if(firstDayOfYear.getDay() != syslib.date.weekStartDay){
			if(week == 1){
				// clone the object
				var workDay = new Date();
				workDay.setTime(day.getTime());
				
				// reduces one day on the date
				workDay.setDate(workDay.getDate() - 1);
				
				// call this same function
				return syslib.date.getWeekOfYear(workDay);
			} else {
				return week - 1;
			}
		} else {
			return week;
		}
	},

	getLocaleDate : function(){
		dateObj = new Date();
		return dateObj.toLocaleDateString();
	},

	validate : function(theDate){
		var reDate = /^((0[1-9]|[12]\d)\/(0[1-9]|1[0-2])|30\/(0[13-9]|1[0-2])|31\/(0[13578]|1[02]))\/\d{4}$/;
		if(!reDate.test(theDate)){
			return false;
		} else {
			return true;
		}
	},
	 
	__prototype : {
		getWeekOfYear : function(){
			return syslib.date.getWeekOfYear(this);
		}
	}
};

/**
 * Aliases and extensions for date class
 */
syslib.object.extend(Date.prototype, syslib.date.__prototype);
syslib.object.extend(Date, syslib.date);

/**
 * The class that controls the ajax requests
 * @class syslib.ajax
 * @author Gabriel Ricci
 * @static
 */
syslib.ajax = {
	createRequestObject : function(){
		var request = false;
		if (window.XMLHttpRequest) {
            request = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            try {
                request = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    request = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
					syslib.messages.error("Your browser doesn't support XMLHTTP [AJAX] Requests!");
					request = false;
				}
            }
        }

		// retorna
        return request;
        
	},

	getDefaultOptions : function(){
		var options = {
			destiny : false,
			clearDestiny : true,
			method : 'POST',
			charset : "UTF-8",
			contentType :  'application/x-www-form-urlencoded',
			parameters : '',
			asynchronous : true,
			form: false,
			store : true,
			evalTags : true,
			evalScripts : true,
			evalStyles : true, 

			callHandlers : true
		};

		return options;
	},

	getDefaultRequestHeaders : function(){
		var headers = {
	      'X-Requested-With': 'XMLHttpRequest',
	      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
	    };
	},

	evalStyles : function(text){
		firstPos = text.indexOf("<style");
		while(firstPos != -1){
			endFirstPos = text.indexOf(">", firstPos + 1);
			endPos = text.indexOf("</style>", endFirstPos + 1);
			elText = text.substring((endFirstPos + 1), endPos);

			elemento = document.createElement("style");
			elemento.text = elText;

			document.body.appendChild(elemento);

			firstPos = text.indexOf("<style", endPos + 1);
		}
	},

	evalScripts: function(text){
		var regex 		= /<script[^>]*>([\u0001-\uFFFF]*?)<\/script>/;
		var matches 	= text.match(regex);
		if(!syslib.util.valid(matches)){
			return true;
		}

		for(var i = 0; i < matches.length; i++){
			var scriptFragment = matches[i];
			if(!scriptFragment.match(regex)){
				try{
					eval(scriptFragment);
				} catch(e){
					syslib.messages.error("Javascript error on request response: " + e.message);
				}
			}
		}
	}
};

/**
 * The ajax request class
 * @class syslib.ajax.request
 * @author Gabriel Ricci
 */
syslib.ajax.request = __class();
syslib.ajax.request.prototype = {
	url		: null,
	options : null,
	headers : null,
	request : null,

	__construct : function(url, options, headers){
		if(!syslib.util.valid(options)){ options = {}; }
		if(!syslib.util.valid(headers)){ headers = {}; }

		this.url			= url;
		this.request	= syslib.ajax.createRequestObject();
		this.headers	= syslib.object.extend(syslib.ajax.getDefaultRequestHeaders(), headers);
		this.options 	= syslib.object.extend(syslib.ajax.getDefaultOptions(), options);
		
		if(this.options.callHandlers){
			syslib.ajax.handlers.__onCreate(this.request, this.options);
		}
		
		this.prepareParameters();
		this.prepareAndSend();
	},

	prepareParameters : function(){
		if(this.url.indexOf("?") !== -1){
			var data = this.url.split("?");
			this.options.parameters += data[1];
		}

		if(syslib.util.valid(this.options.form) && typeof this.options.form === 'object'){
			this.options.parameters += "&" + syslib.form.serialize(this.options.form);
			this.options.store = false;
		}

		if(this.options.method.toLowerCase() == 'get'){
			this.url += "?" + this.parameters;
		}
	},

	prepareAndSend : function(){
		if(this.options.method.toLowerCase() == 'post'){
			this.headers["Content-type"] = this.options.contentType + ( this.options.encoding ? '; charset=' + this.options.encoding : '');
		}

		if(this.request.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005){
			this.headers["Connection"] = 'close';
		}

    	this.request.open(this.options.method, this.url, this.options.asynchronous);

		this.request.onreadystatechange = syslib.functions.applyTo(function(){
			this.readyStateChanged();
		}, this);

		for(var header in this.headers){ this.request.setRequestHeader(header, this.headers[header]); }

		this.request.send(this.options.parameters);
	},

	readyStateChanged : function(){
		if(this.request.readyState === 4){
			syslib.ajax.handlers.__onComplete(this.request, this.options);
			if(this.request.status === 200){
				this.onSuccess();
				if(typeof this.options.onSuccess === 'function'){ this.options.onSuccess(this.request, this.options); }
			} else {
				this.onError();
				if(typeof this.options.onError === 'function'){ this.options.onError(this.request.status, this.request, this.options); }
			}
		}
	},

	onSuccess : function(){
		if(syslib.util.valid(this.options.destiny)){
			var destiny = __id(this.options.destiny);
			if(this.options.clearDestiny){ syslib.element.update(destiny, ''); }
			if(this.options.evalTags){
				var domTree = syslib.taglib.parseAndAppend(this.request.responseText, destiny);
			} else {
				destiny.innerHTML += this.request.responseText;
			}

			if(this.options.store === true){ syslib.history.addEntry(destiny.id, this.url); }
		}
		if(this.options.evalStyles){ syslib.ajax.evalStyles(this.request.responseText); }
		if(this.options.evalScripts){ syslib.ajax.evalScripts(this.request.responseText); }
	},

	onError : function(){
		syslib.messages.error("Could not complete the requet, the server returned the error code " + this.request.status);
	}
};

/**
 * The ajax request event handlers
 * @class syslib.ajax.handlers
 */
syslib.ajax.handlers = {
	__onCreate : function(){},
	__onComplete : function(){}, 
	
	/**
	 * Set the default handler when the event LOADING has been triggered
	 * @param {Function} handler The handler
	 */ 
	onLoading : function(handler){
		if(typeof handler == 'function'){
			syslib.ajax.handlers.__onCreate = handler;
		} else {
			syslib.messages.error("syslib.ajax.handlers.onLoading(): Invalid loading handler: Undefined, null or not a function!");
		}
	},

	/**
	 * Set the default handler when the event COMPLETE has been triggered
	 * @param {Function} handler The handler
	 */ 
	onComplete : function(handler){
		if(typeof handler == 'function'){
			syslib.ajax.handlers.__onComplete = handler;
		} else {
			syslib.messages.error("syslib.ajax.handlers.onComplete(): Invalid loading handler: Undefined, null or not a function!");
		}
	}
};

/**
 * The older ajax requests class (replaced by syslib.ajax)
 * @class syslib.request
 * @author Gabriel Ricci
 * @deprecated
 */
syslib.request = {
	get : function (requestFile, container, options, getParameters){
		options = (typeof options == 'object') ? options : {};

		options.destiny	= (!syslib.util.valid(container)) ? false : container;
		requestFile 	= (syslib.util.valid(getParameters)) ? requestFile + "?" + getParameters : requestFile;

		var request = new syslib.ajax.request(requestFile, options);
	},

	openPage : function(page, args){
		if(args === undefined || args === "undefined"){
			window.open(page, 'newPage');
		} else {
			window.open(page, 'newPage', args);
		}
	},

	setLoadingHandler : syslib.ajax.handlers.onLoading,
	setResponseHandler : syslib.ajax.handlers.onComplete
};

/**
 * The input/output class
 * @class syslib.io
 * @author Gabriel Ricci
 * @static
 */
syslib.io = {
	// SET THE STATES
	LOADING : 0,
	LOADED : 1,
	ERROR : 2,

	// SETA O TIMEOUT
	TIMEOUT : 13,

	scripts : {},
	styles : {},

	checkScript : function(filename, attempt){
		if(this.scripts[filename] != this.LOADED){
			if(attempt >= this.TIMEOUT){
				this.scripts[filename] = this.ERROR;
			} else {
				setTimeout(function(){
					this.checkScript(filename, attempt++);
				}, 1000);
			}
		}
	},

	importClass  : function(className, options){
		// FORMAT THE OPTIONS
		options = syslib.object.extend({
			"className" : className
		}, options);

		// FORMAT THE PATH
		var path = syslib.srcPath
					+ syslib.string.replace(".", "/", syslib.string.replace("syslib.", "", className))
					+ ".js";

		// IMPORT
		var filename = this.importScript(path, options);

		return filename;
	},

	importScript : function(filename, options){
		// FORMAT THE OPTIONS
		options = syslib.object.extend({
			onComplete : function(){
				return;
			}
		}, options);

		// CHECK IF ITS ALREADY LOADED
		var scripts = this.scripts;
		for(var script in scripts){
			if(script == filename){
				if(scripts[filename].state == this.LOADED){
					syslib.messages.info('syslib.io.importScript(): script ' + filename + ' is already loaded, , calling onComplete() !');
					scripts[filename].onComplete(filename);
				}
				return;
			}
		}
		
		// STORES
		syslib.io.scripts[filename] = {
			state : this.LOADING,
			onComplete : options.onComplete,
			filename : filename
		};
		
		// ANTI-CACHE PROCESS
		if(filename.indexOf("?") != -1){
			var filenameAc = filename + "&ac=" + Math.floor(Math.random()*1111);
		} else {
			var filenameAc = filename + "?ac=" + Math.floor(Math.random()*1111);  
		}
		
		// LOG
		syslib.messages.info('syslib.io.importScript(): Trying to load script ' + filenameAc + " !");

		// CREATE THE SCRIPT
		var script = document.createElement("script");
		script.setAttribute("src", filenameAc);
		document.getElementsByTagName('head')[0].appendChild(script);

		// EVENTS
		script.onreadystatechange = function(){
			if(this.readyState == "complete" || "loaded"){
				var file = this.getAttribute("src");
				syslib.io.scripts[filename].state =  syslib.io.LOADED;
				syslib.io.scripts[filename].onComplete(filename);
			}
		};
		script.onload = function(){
			var file = this.getAttribute("src");
			syslib.io.scripts[filename].state =  syslib.io.LOADED;
			syslib.io.scripts[filename].onComplete(filename);
		};

		return filename;
	},

	importStyle : function(filename){
		// CHECK
		var styles = this.styles;
		for(var style in styles){
			if(style == filename){
				return;
			}
		}

		// IMPORT
		var style 	= document.createElement("link");
		style.rel 	= 'stylesheet';
		style.type 	= 'text/css';
		style.href 	= filename;
		document.getElementsByTagName('head')[0].appendChild(style);

		// EVENTS
		styles[filename] = this.LOADED;
	}
};

Request 		= syslib.request;
System			= syslib;
Helpers			= syslib.util;
Util			= syslib.util;
History			= syslib.history;